#!/usr/bin/env python
# coding: utf-8
import pdb
import os
import re
import shutil
import zipfile
import time
import datetime
import string
from onshs.tnxxxcfg_basecase import *

pdb.set_trace()

log_node_prefix = "common_script"
log_node_fail = log_node_prefix+r"_fail"
log_node_success = log_node_prefix+r"_success"
log_node_operation = log_node_prefix+r"_operation"

log_file_notexisted_fail = "the file:%s isn't existed\n"
log_connect_fail         = "connect ip:%s failed\n"
log_master_opca_fail     = "get ip:%s master opca is failed\n"

operation_command        = "operation ip:%s slot:%s port:%s command:%s"
success_command          = "success ip:%s slot:%s port:%s command:%s"
fail_command             = "fail ip:%s slot:%s port:%s command:%s"

'''
如果需要校验命令是否执行成功，需要判断是否有success_condition关键字，如果有，就需要在返回值中检查是否包含success_condition关键字
对应的内容。
--success_condition代表判断返回值成功与否的标志，如果成功，继续下一步骤，记success log；如果失败,记fail log，继续下一槽位。
如果需要提取命令返回值并且作为其他命令的输入，那么可以如下参数。
--buffer_parameter代表对于返回值采用正则表达式进行提取，取出来的值相应保存在buffer_parameter中，之后可以作为命令输入参数使用。
解析每条命令时，需要判断是否有buffer_parameter关键字，如果有，就需要用脚本中保存的值进行替换。如果没有，不需要操作。
query console mac --reture_filter1 \dsuccess.+ --success_conditon success
query console mac --success_conditon success
query console mac --reture_filter1 \dsuccess.+ 
query console mac --success_conditon success --reture_filter1 \dsuccess.+
query console mac mac buffer_parameter1
set system mac buffer_parameter1--success_conditon
处理过程：
1.先替换buffer_parameter,截掉“ --”起始的后面的内容执行命令，得到返回值。
2.查找“ --”起始的后面的内容。
如果有condition，比较正确，记success log，继续看是否有re，如果有就保存到相应的buffer_parameter中。由于re的参数错误，程序最可能在这里异常。
                 比较错误，记fail log。
如果没有，则记operation log。
希望从输出结果提取到什么，需要提供给杭州，杭州进行调试后给出参数。

注意事项，由于6000端口root用户的密码可能会修改，因此需要使用3333端口命令得到root用户的密码，传递给6000端口命令使用。

对于common script的第一个使用案例snmp configuation而言，只有如下情况：
set command
query command --success_condition wangfei
switch(config)#set snmp rwcommunity 2 default
switch(config)#show snmp config
Type           Value
rwcommunity    wangfei
rocommunity    help1
rwcommunity    1 1.1.1.1 1.3.4
rwcommunity    2 default
switch(config)#
'''

buffer_key_dic = {
    "buffer_parameter1"        : '',
    "buffer_parameter2"        : '',
    "buffer_parameter3"        : '',
    "buffer_parameter4"        : '',
    "buffer_parameter5"        : '',
    "buffer_parameter6"        : '',
    "buffer_parameter7"        : '',
    "buffer_parameter8"        : '',
    "buffer_parameter9"        : '',   
}

common_card_config = {
"opca":["opca_23.txt","opca_2650.txt","opca_3333.txt","opca_6000.txt","opca_9999.txt"],
"n64f01":["pos_23.txt","pos_3333.txt"],
"n16f01":["pos_23.txt","pos_3333.txt"],    
}

class TestCase (TnxxxCfg_BaseCase) :
    """
    TestCase
    """
    OPTIONS = [        
        {
            'opt' : '--cfgfile',
            'dest': 'cfgfile',
            'metavar' : 'CFGFILE',
            'help' : 'the file of ip list configuration',
            'required' : False,
            'default' : "ip.txt"
        },     
    ]
       
    def get_iplist(self):
        iplist_filted = []                
        if os.path.isfile(os.getcwd()+r'/'+ self.iplistfile):
            iplist = open(os.getcwd()+r'/'+ self.iplistfile)            
        else:
            self.info_show(log_node_fail, log_file_notexisted_fail%(self.iplistfile))            
            return iplist_filted 
        
        for line in iplist:
            if re.match(r'^\s*$', line) is not None : continue # 忽略空白行
            if re.match(r'^\s*#', line) is not None : continue # 忽略注释行            
            iplist_filted.append(line.strip('\n'))        
            
        iplist.close()
        
        return iplist_filted     
   
    def info_show(self, node, info):
        if not self.info_dic.has_key(node):
            self.info_dic[node] = ""
        self.info_dic[node] += info + '\n'
        return True

    def info_file_clear(self):
        if os.path.exists(self.work_path+r'/common_log'):
            shutil.rmtree(self.work_path+r'/common_log')
        
        return True    
    
    def info_file_save(self):
        path = self.work_path+r'/common_log/'
        if not os.path.isdir(path):
            os.makedirs(path)
       
        for node in self.info_dic:
            info_list = open(path+node+'_'+self.worktime+'.txt','a')            
            info_list.write(self.info_dic[node])
            info_list.close()
        return True
    
    def info_init(self):
        self.info_dic = {}     
              
        return True                        
    #return phycard_list = [[["slot1"],"cardtype1"],[["slot2"],["cardtype2"]],...]    
    def get_phycard(self, ip):
        phycard_list = []
        if not self.tnxxx.send("configure terminal", ip=ip, slot=0, port=CLI_PORT):
            self.info_show(log_node_fail, log_connect_fail%(ip))
            return phycard_list
        rtn_str = self.tnxxx.send_rtn_str("show card", ip=ip, slot=0, port=CLI_PORT)
        if not self.tnxxx.send("exit", ip=ip, slot=0, port=CLI_PORT):
            self.info_show(log_node_fail, log_connect_fail%(ip))
            return phycard_list
        
        phycard_list = re.findall(r"slot:\s+(\d+)\s+stat:\s+\w+\s+Card:\s+(\w+)\s+", rtn_str, re.I)
        return phycard_list
    
    def get_master_opca(self):
        query_masterppc_cmd = '''$.dbgcli.0.Cmd "queryasyn valid 1, NeStat, (MasterPPC), *"'''
        rtn_str = None        
        rtn_str = self.tnxxx.send_rtn_str(query_masterppc_cmd, self.get_ne_ip(0), 0, MTN_PORT)
        if [] == re.findall('success', rtn_str) or [] == re.findall('\d',rtn_str):         
            self.info_show(log_node_fail, log_master_opca_fail%(self.get_ne_ip(0)))            
            return False
        else:            
            self.master_opca = int(re.findall('\d',rtn_str)[0])                                  
            return True
    
    def execute_for_command(self,ip,slot,port,command):
        #command_list = ['set snmp rwcommunity buffer_parameter1 buffer_parameter2','success_condition ','buffer_parameter1 (buffer_parameter\d)']
        command_list = re.split(" --",command)
        success_flag = None
        re_key_dic = {}
        for index,command in enumerate(command_list):
            #sub command's buffer_parameter 
            if 0 == index:
                detail_commmand = command
                for key in buffer_key_dic.keys():                             
                    detail_commmand = re.sub(key,buffer_key_dic[key],detail_commmand)
                continue
            
            #success condition operation:
            if []!= re.findall('success_condition ',command):
                success_flag = re.findall("(?<=success_condition ).*",command)[0]
            #re operation
            else:
                re_key_dic[re.findall("buffer_parameter\d",command)[0]]= re.findall("(?<=buffer_parameter\d ).+",command)[0]    
            
        rtn_str = self.tnxxx.send_rtn_str(detail_commmand, ip, slot, port)
        if None == success_flag:
             self.info_show(log_node_operation, operation_command%(ip,str(slot),str(port),detail_commmand))
        elif [] != re.findall(success_flag,rtn_str):
             self.info_show(log_node_success, success_command%(ip,str(slot),str(port),detail_commmand))
        else:
             self.info_show(log_node_fail, fail_command%(ip,str(slot),str(port),detail_commmand))
             return False
        
        for key in re_key_dic.keys():
            buffer_list = re.findall(re_key_dic[key],rtn_str)
            if [] != buffer_list:
                buffer_key_dic[key] = buffer_list[0]
        return True
                
    def update_root_password(self,ip,slot,port):        
        command = '''$.dbgcli.0.Cmd "queryasyn valid 1, UsrInfo, (Psw), Name='root'" --buffer_parameter1 (?<=  ").*(?="\r)'''        
        self.execute_for_command(ip,slot,3333,command)
        support_port_dic[port][2] =  buffer_key_dic["buffer_parameter1"]     
                       
    def common_cmd(self, ip) :
        self.update_root_password(ip,self.master_opca,6000)
        phycard_list = self.get_phycard(ip)
        if [] == phycard_list:
            return False
        for phycard in phycard_list:            
            slot = int(phycard[0])
            card_name = phycard[1]
            
            if card_name not in common_card_config.keys() :
                continue
            
            for cmd_file in common_card_config[card_name] :
                m = re.match(r'[\w\d]+_(\d+)', cmd_file)
                port = int(m.group(1))
                if (6000 == port or 2650 == port) and (slot != self.master_opca):
                    continue                     
                
                cmd_list = open(self.work_path+r'/common_cmd/'+cmd_file)
                for line in cmd_list:
                    if re.match(r'^\s*$', line) is not None:
                        continue # 忽略空白行
                    if re.match(r'^\s*#', line) is not None:
                        continue # 忽略注释行
                    if False == self.execute_for_command(ip,slot,port,line):
                        break                
                        
                cmd_list.close()
                
        return True

            
    def _execute(self):
        self.work_path = os.getcwd() 
        self.info_file_clear()
        self.info_init()
        
        worktime = str(datetime.datetime.now())
        self.worktime = worktime[:4]+worktime[5:7]+worktime[8:10]+'_'+worktime[11:13]+worktime[14:16]+worktime[17:19]
        
        self.iplistfile = self.options.cfgfile                    
        ip_list = self.get_iplist() 
       
        for ip in ip_list:                    
            print(ip)
            # self.set_ne_ip(0, ip)
            # self.master_opca = 0
            # if False == self.get_master_opca():
            #     continue
            # self.common_cmd(ip)          
            
        # self.info_file_save() 
        return True       

if __name__ == "__main__" :
    case = TestCase()
    case.execute()
          
